import * as THREE from 'three'

import {OrbitControls} from "three/addons/controls/OrbitControls.js"

import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';

import {contours,sphere} from "./contours.js"

const renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.toneMapping = THREE.NeutralToneMapping;//ReinhardToneMapping;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.autoClear = true;
renderer.setClearColor('#000', 1);
document.body.appendChild(renderer.domElement);
const gl = renderer.getContext()

const scene = new THREE.Scene();

const width = window.innerWidth;
const height = window.innerHeight;
const camera = new THREE.PerspectiveCamera(45,width / height,0.01,200);

camera.position.set(-1.3, 1.27, 1.9) //focus on thrax
//camera.up.set(0, 0, 1);
camera.lookAt(0, 0, 0);

const controls = new OrbitControls(camera,renderer.domElement);
// controls.maxPolarAngle = Math.PI * 0.5;
controls.minDistance = 0.01;
controls.maxDistance = 100;
controls.enableDamping = true;

let pointLight = new THREE.PointLight('white',10.);
camera.add(pointLight);
scene.add(camera)

const renderScene = new RenderPass( scene, camera );

const bloomPass = new UnrealBloomPass( new THREE.Vector2( window.innerWidth, window.innerHeight ), 1.5, 0.4, 0.85 );
bloomPass.threshold = 0.;
bloomPass.strength = 0.4;
bloomPass.radius = .05;

const outputPass = new OutputPass();

let composer = new EffectComposer( renderer );
composer.addPass( renderScene );
composer.addPass( bloomPass );
composer.addPass( outputPass );

let handleResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
  composer.setSize(window.innerWidth, window.innerHeight)
}
handleResize();
window.addEventListener('resize', handleResize, false)

let sharedUniforms={};

contours.userData.sharedUniforms = sharedUniforms;
contours.frustumCulled = false;
sphere.material.opacity = 1.;
scene.add(sphere);
scene.add(contours);

import sim from "./sim.js"
let {streaks,uniforms,drawUpdateParticles,debugMesh,windFiles,loadWind,setPalette,rebuildVisualizer}=sim;

debugMesh && scene.add(debugMesh)

Object.assign(sharedUniforms,uniforms);
scene.add(streaks);





import GUI from "../../lib/lil-gui.module.min.js"
const gui = new GUI(renderer.domElement.parentElement).title('settings')
const streakFolder = gui.addFolder( 'streaks' );

let addGui=(folder,name,min=0,max=1)=>folder.add({value:uniforms[name].value},'value',min,max,.001).name(name).onChange(v=>uniforms[name].value=v)
addGui(streakFolder,'u_speed_factor',.02);
addGui(streakFolder,'u_drop_rate');
addGui(streakFolder,'u_drop_rate_bump');
addGui(streakFolder,'u_spherize');

streakFolder.add(sphere.material,'opacity',0,1,.01).name('sphere opacity')
streakFolder.addColor(contours.material,'color').name('outline color')
streakFolder.add({size:sim.streaks.material.size},'size',0.001,.1,.00001).onChange(v=>sim.streaks.material.size=v)
streakFolder.add({instanceCount:sim.streaks.geometry.instanceCount},'instanceCount',0,sim.streaks.geometry.instanceCount,1).onChange(v=>sim.streaks.geometry.instanceCount=v);
let fileKeys = Object.keys(windFiles);
streakFolder.add({number:0},'number',windFiles).name('wind snapshots').onChange(loadWind)

streakFolder.add({primitive:0},'primitive',{points:1,lines:0}).onChange(rebuildVisualizer)

streakFolder.add(sphere.material,'map',{
  none:null,
  map:uniforms.u_wind.value,
  earth:new THREE.TextureLoader().load('./assets/earth-blue-marble.jpg'),
  topo:new THREE.TextureLoader().load('./assets/earth-topology.png')
}).name('show wind tex').onChange(v=>{
  if(v)sphere.material.color.set('white')
  else sphere.material.color.set('black')
})
streakFolder.add(debugMesh,'visible').name('debug mesh')

const colorFolder = gui.addFolder( 'color' );
colorFolder.add({palette:0},'palette',0,6,1).onChange(setPalette);
addGui(colorFolder,'u_palScale');
addGui(colorFolder,'u_palBias');
colorFolder.addColor(uniforms.u_palBoost,'value').name('u_palBoost').onChange(v=>{

});
const bloomFolder = gui.addFolder( 'bloom' );
bloomFolder.add(bloomPass,'strength',0.,2.);
bloomFolder.add(bloomPass,'threshold',0.,2.);
bloomFolder.add(bloomPass,'radius',0.,2.);
bloomFolder.add( {exposure:1}, 'exposure', 0.1, 2 ).onChange(value=>renderer.toneMappingExposure = Math.pow( value, 4.0 ));
//streakFolder.close();
//colorFolder.close();
//bloomFolder.close();
gui.close();


sphere.material.map = uniforms.u_wind.value;

//scene.add(new THREE.AxesHelper())

function animate() {
  drawUpdateParticles(renderer)
  renderer.setRenderTarget(null)
  if(controls.target.length()>1)controls.target.setLength(1);
  controls.update()
  composer.render();
  //renderer.render(scene, camera)
  requestAnimationFrame(animate)
}
animate()
